package dfvs

import (
	"encoding/base64"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/sirupsen/logrus"
	"math"
	"time"
)

const (
	// FiberOK 光纤正常
	FiberOK FiberStatus = iota
	// FiberNoInsert 光纤未插入
	FiberNoInsert
	// FiberBreak 光纤断裂
	FiberBreak
	// FiberTooLong 光纤过长
	FiberTooLong
)

const (
	AlarmLevelNone AlarmLevel = iota
	// AlarmLevel1 一级报警
	AlarmLevel1
	// AlarmLevel2 二级报警
	AlarmLevel2
	// AlarmLevel3 三级报警
	AlarmLevel3
)

func FiberStatusFrom(str string) FiberStatus {
	switch str {
	case "None":
		return FiberOK
	case "NoFiber":
		return FiberNoInsert
	case "Break":
		return FiberBreak
	case "TooLong":
		return FiberTooLong
	default:
		return FiberOK
	}
}

func (l AlarmLevel) String() string {
	switch l {
	case AlarmLevelNone:
		return "正常"
	case AlarmLevel1:
		return "一级"
	case AlarmLevel2:
		return "二级"
	case AlarmLevel3:
		return "三级"
	}
	return "未知"
}

func (s FiberStatus) String() string {
	switch s {
	case FiberOK:
		return "正常"
	case FiberNoInsert:
		return "未插入"
	case FiberBreak:
		return "断裂"
	case FiberTooLong:
		return "过长"
	}
	return "未知"
}

type (
	FiberStatus byte

	AlarmLevel byte

	Handle interface {
		Alarm(MQTTChannelAlarm)

		Fiber(MQTTChannelFiber)

		Signal(MQTTChannelSignal)
	}

	Message struct {
		Level   logrus.Level
		Message string
		At      time.Time
	}

	SensorChannel struct {
		SensorId       string
		ChannelId      byte
		AlarmLevel     AlarmLevel
		AlarmInterval  time.Duration
		AlarmPrecision float32

		latestAlarmTime     time.Time
		latestAlarmLocation float32
	}

	// MQTTChannelAlarm  从MQTT获取的报警数据
	MQTTChannelAlarm struct {
		TypeID         uint32    //样本ID
		TypeName       string    //样本名
		Level          int32     //匹配级别值为1或2或3 三种匹配级别
		Possibility    float32   //匹配率
		CenterPosition float32   //事件中心
		EventWidth     float32   //事件宽度
		FirstPushTime  string    //第一次推送时间
		MaxIntensity   float32   //最大强度
		SensorID       string    //机器码
		ChannelID      byte      //通道ID
		PushTime       string    //推送时间
		LastPushTime   string    //最后一次推送时间
		At             time.Time `json:"-"` // 解析时间用
		LastAt         time.Time `json:"-"`
	}

	// MQTTChannelFiber 通道光纤状态
	MQTTChannelFiber struct {
		FiberStatusText  string      `json:"FiberStatus"` //光纤状态
		FiberStatus      FiberStatus `json:"Status"`      //光纤状态
		FiberBreakLength float32     //光纤断点位置
		FiberRealLength  float32     //光纤实际长度
		SensorID         string      //机器码
		ChannelID        byte        //通道
		PushTime         string      //推送时间
		At               time.Time   `json:"-"`
	}

	// MQTTChannelSignal ChannelSignal 通道信号
	MQTTChannelSignal struct {
		SensorID   string  //机器码
		ChannelID  byte    //通道
		RealLength float32 //实际长度
		Signal     []byte  //信号点集合
	}

	MQTTHeartbeat struct {
		SensorID string     `json:"sensor_id"` //机器码
		LastAt   string     `json:"last_at"`   //上一次推送时间
		Now      string     `json:"now"`       //当前推送时间
		At       *time.Time `json:"-"`
	}
)

// ToSignal
// ToSignal 解码信号数据
// | 0_35| 36 |37_40|41_|
// |机器码|通道 | 长度 |信号|
func ToSignal(data []byte) (*MQTTChannelSignal, error) {
	d, err := base64.StdEncoding.DecodeString(string(data))
	if err != nil {
		return nil, err
	}
	if len(d) < 40 {
		return nil, errors.New("invalid signal length")
	}
	return &MQTTChannelSignal{
		SensorID:   string(d[:36]),
		ChannelID:  d[36],
		RealLength: math.Float32frombits(binary.LittleEndian.Uint32(d[37:41])),
		Signal:     d[42:],
	}, nil
}

func (a *MQTTChannelAlarm) Id() string {
	return SetId(a.SensorID, a.ChannelID)
}

func (a *MQTTChannelFiber) Id() string {
	return SetId(a.SensorID, a.ChannelID)
}

func (a *MQTTChannelSignal) Id() string {
	return SetId(a.SensorID, a.ChannelID)
}

func (s *SensorChannel) Id() string {
	return SetId(s.SensorId, s.ChannelId)
}

func SetId(sensor string, channel byte) string {
	if len(sensor) >= 8 {
		return fmt.Sprintf("%s-%02d", sensor[:7], channel)
	}
	return fmt.Sprintf("%s-%02d", sensor, channel)
}
